home *** CD-ROM | disk | FTP | other *** search
- *
- * C initial startup procedure under AmigaDOS
- *
-
- INCLUDE "exec/types.i"
- INCLUDE "exec/alerts.i"
- INCLUDE "exec/nodes.i"
- INCLUDE "exec/lists.i"
- INCLUDE "exec/ports.i"
- INCLUDE "exec/libraries.i"
- INCLUDE "exec/tasks.i"
- INCLUDE "exec/memory.i"
- INCLUDE "exec/execbase.i"
- INCLUDE "libraries/dos.i"
- INCLUDE "libraries/dosextens.i"
- FUNCDEF MACRO * function
- _LVO\1 EQU FUNC_CNT
- FUNC_CNT SET FUNC_CNT-6
- ENDM
-
- FUNC_CNT SET LIB_NONSTD
-
- INCLUDE "exec/exec_lib.i"
- INCLUDE "libraries/dos_lib.i"
- INCLUDE "workbench/startup.i"
-
- AbsExecBase EQU 4
-
- TINY EQU 0
- callsys macro
- CALLLIB _LVO\1
- endm
-
- xdef XCEXIT ; exit(code) is standard way to leave C.
- xdef @XCEXIT
-
- xref LinkerDB ; linker defined base value
- xref _BSSBAS ; linker defined base of BSS
- xref _BSSLEN ; linker defined length of BSS
-
- xref _main ; Name of C program to start with.
- xref __fpinit * initialize floating point
- xref __fpterm * terminate floating point
-
- * library references
-
- csect _NOMERGE,0,0,0,4
- xref MemCleanup
- xref FindTask
-
- start:
- movem.l d1-d6/a0-a6,-(a7)
- REGSIZE EQU (6+7)*4
- lea REGSIZE(a7),A5 * determine old stack pointer
- move.l a0,a2 * save command pointer
- move.l d0,d2 * and command length
- lea LinkerDB,a4 * load base register
-
- move.l AbsExecBase.W,a6
- move.l a6,SysBase(A4)
- move.l a7,_StackPtr(A4) * Save stack ptr
- clr.l WBenchMsg(A4)
-
- *------ Clear out our BSS section
- lea _BSSBAS,a3 * get base of BSS
- moveq #0,d1
- move.l #_BSSLEN,d0 * get length of BSS in longwords
- bra.s clr_lp * and clear for length given
- clr_bss move.l d1,(a3)+
- clr_lp dbf d0,clr_bss
-
- *------ get the address of our task
- move.l ThisTask(a6),A3
-
- *----- clear any pending signals
- moveq #0,d0
- move.l #$00003000,d1
- callsys SetSignal
-
- *------ are we running as a son of Workbench?
- move.l pr_CurrentDir(A3),curdir(A4)
- tst.l pr_CLI(A3)
- beq fromWorkbench
-
- *=======================================================================
- *====== CLI Startup Code ===============================================
- *=======================================================================
-
- fromCLI:
- *------ attempt to open DOS library:
- bsr.w openDOS
-
- *------ Duplicate the current directory for the called process
- move.l curdir(A4),D1
- move.l DOSBase(A4),A6
- callsys DupLock
- move.l D0,curdir(A4)
-
- *------ find command name:
- move.l pr_CLI(A3),a0
- add.l a0,a0 ; bcpl pointer conversion
- add.l a0,a0
- move.l cli_CommandName(a0),a1
- add.l a1,a1 ; bcpl pointer conversion
- add.l a1,a1
-
- *------ collect parameters:
- move.l d2,d0 ; get command line length
- moveq.l #0,d1
- move.b (a1)+,d1
- move.l A1,D4 ;save our pointer
- move.l d1,d3
- add.l d1,d1 ; double length since we copy it twice
- add.l d1,d0 ; add length of command name
- addq.l #5,d0 ; allow for space after command
- addq.l #4,d0 ; As well as for the roundup
- * ; changed from 5 to 9 for quotes
- *
- *------ We have the length of the command string to be copied.
- *------ Allocate space for it.
- *------ Round up to the nearest 4 bytes
- lsl.l #2,d0
- add.l memsize(A4),d0
- move.l d0,memsize(A4)
-
- ************************************************************************
- ************************************************************************
- ******** Allocate and copy over the code to do the magic stuff *********
- ************************************************************************
- ************************************************************************
-
- lea memlist(A4),A0
- move.l AbsExecBase.W,a6
- callsys AllocEntry ;get a place to put the code
- * btst.l #31,d0 ;did we get the memory we asked for?
- * beq cliexit ;no, can't do anything then
- move.l D0,A1
- move.l D0,-(A7) ;remember the chunk we allocated
-
- *------ Now we copy the code over
- movea.l ML_SIZE+ME_ADDR(A1),A1 ;locate our allocated block
-
- *------ Copy over the command line to the allocated area
- lea commandbuf-copybeg(A1),A3
-
- *------ At this point, we have:
- * A0 - Work pointer
- * A1 - Pointer to Allocated memory block
- * A2 - Pointer to program name
- * A3 - Pointer to target buffer
- * A3 - Pointer to our process structure
- * D0 - Work register
- * D1 - Work register
- * D2 - length of command name
- * D3 - length of program name
- * D4 - Pointer to program name
-
- movea.l D4,A0 ; Load program name
- move.l D3,D0 ; and length
- move.b #'"',(a3)+
- bra.s cpy1
- cpycmd: move.b (A0)+,(A3)+ ; copy over the command name
- cpy1: dbf d0,cpycmd
- move.b #'"',(a3)+
- move.b #' ',(A3)+ ; add the space delimiter
-
- move.l A2,A0 ; Load command text
- move.l D2,D0 ; and length
- bra.s cpy2
- cpylin: move.b (A0)+,(A3)+
- cpy2: dbf d0,cpylin
- clr.b (A3)+
-
- *------ Now copy over the program name
- move.l A3,_ProgramName(A4)
- move.l D4,A0
- move.l D3,D0
- bra.s cpy3
- cpypgm: move.b (A0)+,(A3)+
- cpy3: dbf D0,cpypgm
- clr.b (A3) ;don't forget trailing null on name
-
- *------ First we want to put it into our seglist
- lea segexit-copybeg(A1),A2
- move.l A2,XCEXIT+2(A4) ;patch the jump instruction
- lea start-4(PC),A2
-
- * Now we have: A1 to our new fake segment
- * A2 to the start of the real seglist
- move.l #(copyend-copybeg)/4,(A1)+
- move.l A1,D3
- lsr.l #2,D3 ;convert it to a bptr to the list
- move.l (A2),(A1)+ ;save our next segment pointer
- clr.l (A2) ;and kill it from the chain
- *------ We have the seglist
-
- lea AutoLoader(PC),A2
- move.l #(copyend-AutoLoader)-1,D0
- copyit move.b (A2)+,(A1)+
- dbf d0,copyit
-
- *------ See if they want to do some I/O
- tst.l _BackGroundIO(A4)
- beq noio
- lea current_window(A4),A0
- move.l A0,D1
- move.l #1005,D2
- move.l DOSBase(A4),A6
- callsys Open
- move.l d0,_Backstdout(A4)
- noio:
- move.l AbsExecBase.w,A6
-
- *------ If under 2.0 Flush cache
-
- moveq #24,d0
- cmp.w $14(a6),d0
- bcs.b nocache
- moveq #-1,d0
- callsys CacheClearU
-
- nocache:
- callsys Forbid
-
- *------ Attach the task to do the dirty work
- move.l _procname(A4),D1 ; Name of task to start
- move.l _priority(A4),D2 ; Priority of background task
- move.l _stack(A4),D4 ; Stack size of created task
-
- move.l DOSBase(A4),A6
- callsys CreateProc
- move.l A6,A3 ; restore dosbase to close it
- tst.l D0
- bne ok
-
- *------ Serious problems. For some reason the CreateProc failed.
- *------ We need to free the AlocEntry memory and go home
- move.l (A7)+,A2
- movea.l ML_SIZE+ME_ADDR(A2),A1 ;locate our allocated block
- *------ Also must get rid of current directory
- move.l curdir(A4),D1
- callsys UnLock
-
- move.l A2,A0
- move.l AbsExecBase.w,A6
- callsys FreeEntry
- move.l #104,D0
- bra cliexit
-
- ok:
- *------ The task started ok, attach the memory we allocated to
- *------ its task control block
- move.l D0,A2
-
- move.l (a7)+,A1 ;locate the memory we allocated
- lea -pr_MsgPort(A2),A2
- lea TC_MEMENTRY(A2),A0
-
-
- * ADDTAIL
- LEA LH_TAIL(A0),A0
- MOVE.L LN_PRED(A0),D0
- MOVE.L A1,LN_PRED(A0)
- MOVE.L A0,(A1)
- MOVE.L D0,LN_PRED(A1)
- MOVE.L D0,A0
- MOVE.L A1,(A0)
-
- move.l #0,D0
-
- cliexit:
- move.l AbsExecBase.w,A6
- callsys Permit
- move.l A3,A1
- move.l AbsExecBase.w,A6
- callsys CloseLibrary
- movem.l (a7)+,d1-d6/a0-a6
- rts
-
- *=======================================================================
- *====== Workbench Startup Code =========================================
- *=======================================================================
-
- fromWorkbench:
-
- move.l TC_SPLOWER(A3),_base(A4) ; set base of stack
- add.l #128,_base(A4) ;allow for parms overflow
- *------ open the DOS library:
- bsr.w openDOS
-
- lea xcexit(PC),A2
- move.l A2,XCEXIT+2(A4) ;patch the jump instruction
-
- *------ we are now set up. wait for a message from our starter
- bsr.w waitmsg
- move.l d0,WBenchMsg(A4)
- move.l d0,-(SP)
- *
- move.l d0,a2 ; get first argument
- move.l sm_ArgList(a2),d0
- beq.s do_cons
- move.l DOSBase(A4),a6
- move.l d0,a0
- move.l wa_Lock(a0),d1
- callsys DupLock
- move.l d0,curdir(A4)
- move.l d0,d1
- callsys CurrentDir
- do_cons:
- move.l sm_ToolWindow(a2),d1 ; get the window argument
- beq.s do_main
- move.l #MODE_OLDFILE,d2
- callsys Open
- move.l d0,stdin(A4)
- beq.s do_main
- lsl.l #2,d0
- move.l d0,a0
- move.l fh_Type(a0),pr_ConsoleTask(A3)
- do_main:
- move.l WBenchMsg(A4),a0 ; get address of workbench message
- move.l a0,-(a7) ; push argv
- pea NULL(A4) ; push argc
- move.l sm_ArgList(a0),a0 ; get address of arguments
- move.l wa_Name(a0),_ProgramName(A4) ; get name of program
- *------ For startup from workbench, there is no reason to go through
- *------ The fancy stuff to make the startup work. Just run the
- *------ Code directly
- jsr __fpinit(PC)
- jsr _main
- moveq.l #0,d0
- bra.w exit2
-
-
- ************************************************************************
- ************************************************************************
- ************* *************
- ************* Start of code that is copied to fake segment *************
- ************* *************
- ************************************************************************
- ************************************************************************
-
- copybeg:
- DC.L (copyend-copybeg)/4
- next: DC.L 0
- AutoLoader:
- move.l a7,d0
- movem.l d1-d6/a0-a6,-(a7)
- move.l d0,a5
- move.l AbsExecBase.w,a6
- lea LinkerDB,A4 ; load base register
- move.l a7,_StackPtr(A4)
-
- bsr.w openDOS
- suba.l a1,a1
-
- suba.l a1,a1
- callsys FindTask
- move.l d0,A3
-
- move.l TC_SPLOWER(A3),_base(A4) ; set base of stack
- add.l #128,_base(A4) ;allow for parms overflow
-
- move.l pr_SegList(A3),a0 ;locate the segment list
- add.l A0,A0
- add.l A0,A0 ;and convert to an APTR
- move.l 12(A0),A1 ;so we can access the segments
- add.l A1,A1
- add.l A1,A1
-
- move.l (A1),seglist(A4) ;save the remainder for later
- move.l (A1),12(A0) ;cut off our segment
-
- move.l curdir(A4),D1
- move.l DOSBase(A4),a6
- callsys CurrentDir
-
- pea commandbuf(PC)
- jsr __fpinit
- jsr _main ; call C entrypoint
- addq #4,A7
-
-
- *------ Unlock the directory we set up for them
- segexit:
- move.l DOSBase(A4),a6
- move.l curdir(A4),D1
- callsys UnLock
-
- moveq.l #0,d0 ; set successful status
- xcexit:
- exit2:
- IFEQ TINY
- move.l _ONEXIT(A4),d0 ; exit trap function?
- beq.s exit3
- move.l d0,a0
- jsr (a0)
- ENDC
-
- exit3 jsr MemCleanup ; cleanup leftover memory alloc.
-
- jsr __fpterm
-
- done_1c:
- *------ if we ran from CLI, skip workbench cleanup:
- tst.l WBenchMsg(A4)
- beq.s exitToDOS
- move.l DOSBase(A4),a6
- move.l stdin(A4),d1
- beq.s done_4
- callsys Close
- done_4:
-
- *------ return the startup message to our parent
- * we forbid so workbench can't UnLoadSeg() us
- * before we are done:
- move.l curdir(a4),d1
- beq.s done_5
- callsys UnLock
-
- done_5:
- move.l AbsExecBase.w,A6
- callsys Forbid
- move.l WBenchMsg(A4),a1
- callsys ReplyMsg
-
- *------ this rts sends us back to DOS:
- exitToDOS:
- movea.l _StackPtr(a4),a3 ; Put old stack pointer somewhere safe.
-
- *------ They are done so unload them
- move.l seglist(A4),D1
- move.l DOSBase(A4),a6
- callsys UnLoadSeg
-
- move.l a6,a1
- move.l AbsExecBase.w,a6
- callsys CloseLibrary ; close Dos library
-
-
- movea.l a3,SP ; restore stack ptr
- movem.l (a7)+,d1-d6/a0-a6
- rts
-
- *-----------------------------------------------------------------------
- * Open the DOS library:
-
- openDOS
- lea DOSName(A4),A1
- moveq.l #0,D0
- callsys OpenLibrary
- move.l D0,DOSBase(A4)
- beq noDOS
- rts
- *-----------------------------------------------------------------------
- noDOS:
- moveq.l #100,d0
- bra exit2
-
- copyend:
- commandbuf:
-
- ************************************************************************
- ************************************************************************
- ************** **************
- ************** End of code that is copied to fake segment **************
- ************** **************
- ************************************************************************
- ************************************************************************
-
- *-----------------------------------------------------------------------
- * This routine gets the message that workbench will send to us
- * called with task id in A3
-
- waitmsg:
- lea pr_MsgPort(A3),a0 ; our process base
- callsys WaitPort
- lea pr_MsgPort(A3),a0 ; our process base
- callsys GetMsg
- rts
-
- csect __MERGED,1,0,0,4
-
- *------ These externals control the task that is started
- xref _BackGroundIO ; flag to indicate background task
- * ; wants to do I/O
- xref _stack ; stack space for created task
- xref _procname ; name of process to be created
- xref _priority ; priority to create process at
-
- xref DOSBase
- xref MathBase
- xref MathTransBase
- *
- xdef NULL,SysBase,WBenchMsg
- xdef curdir,_mbase,_mnext,_msize,_tsize
- xdef _oserr,_OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
- xdef _SIGINT,_Backstdout
- xdef _ProgramName,_StackPtr,_base
- *
- * cnop 0,4
- memlist ds.b LN_SIZE
- dc.w 1
- dc.l MEMF_PUBLIC
- memsize dc.l copyend-copybeg
-
- XCEXIT
- @XCEXIT dc.w $4ef9
- dc.l 0
- seglist dc.l 0
- NULL dc.l 0 ;
- _base dc.l 0 ; base of stack
- _mbase dc.l 0 ; base of memory pool
- _mnext dc.l 0 ; next available memory location
- _msize dc.l 0 ; size of memory pool
- _tsize dc.l 0 ; total size?
- _oserr equ *
- _OSERR dc.l 0
- _FPERR dc.l 0
- _SIGFPE dc.l 0
- _SIGINT dc.l 0
- _ONERR dc.l 0
- _ONEXIT dc.l 0
- _ONBREAK dc.l 0
- curdir dc.l 0
- SysBase dc.l 0
- WBenchMsg dc.l 0
- _StackPtr dc.l 0
- dosCmdLen dc.l 0
- dosCmdBuf dc.l 0
- stdin dc.l 0
- _Backstdout dc.l 0 ;filehandle for I/O
- _ProgramName dc.l 0
- DOSName dc.b 'dos.library',0
- current_window dc.b '*',0
- END
-